package com.netscenery.yang.model;

import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

import com.netscenery.util.ErrTag;
import com.netscenery.util.XMLTag;
import com.netscenery.yang.YangKeyword;
import com.netscenery.yang.YangStatement;
import com.netscenery.yang.designer.LeafFieldMap;
import com.netscenery.yang.designer.MapInfo;
import com.netscenery.yang.parser.YangParserException;
import com.netscenery.yang.writer.YangFormatter;

public class Import extends ModelElement{
	private MainModule importedModule; 
	private String prefix;
	private String revisionDate;
	
	/**
	 * constructor
	 * @param name
	 * @param prefix
	 */
	public Import(Env env,String name, String prefix){
		this(env,name);
		
		setPrefix(prefix);
	}
	
	/**
	 * constructor
	 * @param name
	 * @param prefix
	 */
	public Import(Env env,String name){
		if (null == env){
			return;
		}
		
		if (null == name){
			return;
		}
		setEnv(env);
		if (!setName(name)){
			return;
		}
		
		Module m = env.getModule(name);
		if (null == m){
			return;
		}
		
		if (m instanceof MainModule){
			this.setImportedModule((MainModule)m);
		}
		else{
			return;
		}
		
		setPrefix(((MainModule)m).getPrefix());
	}
	
	/**
	 * ָ������ģ���prefix����Import
	 * @param m
	 * @param prefix
	 */
	public Import(Env env,MainModule m, String prefix){
		if (null == m){
			return;
		}
		if (null == env){
			return;
		}
		this.setImportedModule(m);
		this.setName(m);
		this.setPrefix(prefix);
		setEnv(env);
	}
	/**
	 * ���ָ��prefix����Ĭ��ʹ�ñ�����ģ���prefix
	 * @param m
	 */
	public Import(Env env,MainModule m){
		if (null == m){
			return;
		}
		if (null == env){
			return;
		}
		this.setImportedModule(m);
		this.setName(m);
		this.setPrefix(m.getPrefix());
		this.prefix = m.getPrefix();
		setEnv(env);
	}
	
	public String getName() {
		return name;
	}
//	public void setName(String name) {
//		this.name = name;
//	}
	
	public boolean setName(MainModule m){
		if (null == m){
			return false;
		}
		
		return setName( m.getName());
	}
	public String getPrefix() {
		return prefix;
	}
	public void setPrefix(String prefix) {
		if (null != env){
			if (env.hasPrefix(prefix)){
				return;
			}
		}
		this.prefix = prefix;
		if (null != env){
			env.addPrefix(prefix);
		}
	}
	public String getRevisionDate() {
		return revisionDate;
	}
	public void setRevisionDate(String revisionDate) {
		if (null == revisionDate){
			return;
		}
		if (!Revision.checkRevisionDate(revisionDate)){
			return;
		}
		if (null != this.getImportedModule()){
			if (null == importedModule.getRevision(revisionDate)){
				return;
			}
		}
		this.revisionDate = revisionDate;
	}
	
	/**
	 * @return the importedModule
	 */
	public MainModule getImportedModule() {
		return importedModule;
	}

	/**
	 * @param importedModule the importedModule to set
	 */
	public void setImportedModule(MainModule importedModule) {
		this.importedModule = importedModule;
	}

	/**
	 * ��Import��ת����XML��ʽ
	 * convert Import to XML
	 * @return
	 */
	public Element toXML(){		
		
		if (null == this.name){
			return null;
		}
		Element importElement = new Element(XMLTag.XML_TAG_IMPORT);
		/*
		 * the module name that is imported.
		 */
		Element name = new Element("name");
		name.setText(this.name);
		importElement.addContent(name);
		/*
		 * the prefix of the module that is imported.
		 * */
		Element prefix = new Element(XMLTag.XML_TAG_PREFIX);
		prefix.setText(this.prefix);
		importElement.addContent(prefix);
		
		if (null != this.revisionDate){
			Element revisionDate = new Element(XMLTag.XML_TAG_REVISIONDATE);
			revisionDate.setText(this.revisionDate);
			importElement.addContent(revisionDate);
		}
		
		return importElement;
		
	}
	
	public static void main(String[] args) {
		MainModule m = null;
		try {
			m = new MainModule(null,"netconf","netc","http://netscenery.com.cn/zxr10/rosng/netconf");
		} catch (ModelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Import importElement = new Import(new Env(),m,"netc");
		importElement.setRevisionDate("2013-01-13");
		YangFormatter formatter = new YangFormatter();
		formatter.setPrettyFormatter();
		System.out.println(importElement.toYANGString(formatter));
		System.out.println(importElement.toXMLString());
	}
	@Override
	public YangStatement toYang() {
		if (null == this.name){
			return null;
		}

		YangStatement statment = new YangStatement(XMLTag.XML_TAG_IMPORT,this.name);
		if (this.prefix != null){
			YangStatement prefix = new YangStatement(XMLTag.XML_TAG_PREFIX,this.prefix);
			statment.addChild(prefix);
		}
		
		if (null != revisionDate){
			YangStatement revisionDateElement = new YangStatement(XMLTag.XML_TAG_REVISIONDATE,this.revisionDate);
			statment.addChild(revisionDateElement);
		}
	
		return statment;
	}
	@Override
	public int readXML(Element element) {
		if (null == element){
			return MODELELEMENT_OK;
		}
		//prefix
		if (element.getName().equals(XMLTag.XML_TAG_PREFIX)){
			this.setPrefix(element.getText());
		}
		//revisionDate
		else if (element.getName().equals(XMLTag.XML_TAG_REVISIONDATE)){
			this.setRevisionDate(element.getText());
		}
		else if (element.getName().equals(XMLTag.XML_TAG_NAME)){
			return MODELELEMENT_OK;
		}	
		else {
			return MODELELEMENT_FAIL;
		}
		
		return MODELELEMENT_OK;
	}
	@Override
	public int readYANG(YangStatement statement) {
		if (null == statement){
			return MODELELEMENT_OK;
		}
		//prefix
		if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_PREFIX)){
			this.setPrefix(statement.getArgument());
		}
		//revisionDate
		else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_REVISIONDATE)){
			this.setRevisionDate(statement.getArgument());
		}
		else {
			return MODELELEMENT_FAIL;
		}
		
		return MODELELEMENT_OK;
	}
	@Override
	public Validator validate() {
		Validator validator = new Validator();
		if (isNullString(name)){
			validator.setIsValid(false);
			validator.addMsg(new Message(this,ErrTag.ERROR,ErrorCode.COMMON_INVALIDNAME));
		}
		
		if (isNullString(prefix)){
			validator.setIsValid(false);
			validator.addMsg(new Message(this,ErrTag.ERROR,"no prefix."));
		}
		
		if (null == this.importedModule){
			validator.setIsValid(false);
			validator.addMsg(new Message(this,ErrTag.ERROR,"the module to be imported is not exists."));
		}
		if (!name.equals(this.importedModule.getName())){
			validator.setIsValid(false);
			validator.addMsg(new Message(this,ErrTag.ERROR,ErrorCode.COMMON_INVALIDNAME));
		}
		
		if (!isNullString(revisionDate)){
			if (!Revision.checkRevisionDate(revisionDate)){
				validator.setIsValid(false);
				validator.addMsg(new Message(this,ErrTag.ERROR,"invalid revision-date."));
			}
			
			if (null == importedModule.getRevision(revisionDate)){
				validator.setIsValid(false);
				validator.addMsg(new Message(this,ErrTag.ERROR,"invalid revision-date."));
			}
		}
		Validator sValidator = super.validate();
		validator.copy(sValidator);
		return validator;
	}
	@Override
	public boolean isFieldMandatory(String field) {
		// TODO Auto-generated method stub
		return false;
	}
	
	public static Import create(Env env,Element element){
		if (null == element ){
			return null;
		}
		
		if (!element.getName().equals(XMLTag.XML_TAG_IMPORT)){
			return null;
		}
		
		Element name = element.getChild(XMLTag.XML_TAG_NAME);
		if (null == name){
			return null;
		}
		
		if (null == env){
			return null;
		}
		String revisionDate = null;
		if (null != element.getChild(XMLTag.XML_TAG_REVISIONDATE)){
			revisionDate = element.getChildText(XMLTag.XML_TAG_REVISIONDATE);
		}
		MainModule imp = (MainModule)(env.getModule(name.getText(),revisionDate));
		if (null == imp){
			return null;
		}
		
		Import i = new Import(env,imp);
		return i;
		
	}
	public static Import create(Env env,String name){
		if (null == name ){
			return null;
		}
		if (null == env){
			return null;
		}
		
		MainModule imp = (MainModule)(env.getModule(name));
		if (null == imp){
			return null;
		}
		
		Import i = new Import(env,imp);
		i.setEnv(env);
		return i;
		
	}

	public  MapInfo getMapInfo() throws SecurityException, NoSuchMethodException {

		MapInfo mapInfo = new MapInfo();
		mapInfo.setClazz(Import.class);
		
//		LeafFieldMap module = new LeafFieldMap();
//		module.setElementClass(MainModule.class);
//		module.setFieldName("importedModule");
//		module.setDisplayName("module");
//		module.setMandatory(true);
//		mapInfo.addBasicField(module);
		
		LeafFieldMap name = new LeafFieldMap();
		name.setFieldName("name");
		name.setMandatory(true);
		mapInfo.addBasicField(name);
		
		LeafFieldMap prefix = new LeafFieldMap();
		prefix.setFieldName("prefix");
		prefix.setMandatory(true);
		mapInfo.addBasicField(prefix);
		
		LeafFieldMap revisionDate = new LeafFieldMap();
		revisionDate.setFieldName("revisionDate");
		revisionDate.setDisplayName("revision-date");
		mapInfo.addBasicField(revisionDate);
		
		
		return mapInfo;
	}

	@Override
	public Element toYin() {
		if (null == this.name){
			return null;
		}

		Element statement = new Element(XMLTag.XML_TAG_IMPORT,env.getNs());
		Attribute module = new Attribute(YangKeyword.MODULE.getKeyword(),this.name);
		statement.setAttribute(module);
		if (!isNullString(this.prefix)){
			Element prefix = new Element(XMLTag.XML_TAG_PREFIX,env.getNs());
			Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(),this.prefix);
			prefix.setAttribute(value);
			statement.addContent(prefix);
		}
		
		if (!isNullString(revisionDate)){
			Element revisionDateElement = new Element(XMLTag.XML_TAG_REVISIONDATE,env.getNs());
			Attribute date = new Attribute("date",this.revisionDate);
			revisionDateElement.setAttribute(date);
			statement.addContent(revisionDateElement);
		}
	
		return statement;
	}

	@Override
	public int readYin(Element statement) throws ModelException {
		if (null == statement){
			return MODELELEMENT_OK;
		}
		//prefix
		if (statement.getName().equals(YangStatement.YANG_STATEMENT_PREFIX)){
			String value = statement.getAttributeValue(YangKeyword.VALUE.getKeyword());
			if (null == value){
				return MODELELEMENT_FAIL;
			}
			this.setPrefix(value);
		}
		//revisionDate
		else if (statement.getName().equals(YangStatement.YANG_STATEMENT_REVISIONDATE)){
			String value = statement.getAttributeValue("date");
			if (null == value){
				return MODELELEMENT_FAIL;
			}
			this.setRevisionDate(value);
		}
		else {
			
			return MODELELEMENT_FAIL;
		}
		
		return MODELELEMENT_OK;
	}

	@Override
	public void update() {
		// TODO Auto-generated method stub
		
	}
}
